package com.zgl.airoleplay.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zgl.airoleplay.entity.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.net.URLEncoder;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Service
public class AiServiceImpl implements AiService {
        @Autowired
        RoleService roleService;
        @Value("${baidu.llm.apiKey}")
        private String llmApiKey;
        @Value("${baidu.llm.url}")
        private String llmUrl;

        @Value("${baidu.llm.model}")
        private String model;

        @Value("${baidu.tts.apiKey}")
        private String ttsApiKey;
        @Value("${baidu.tts.url}")
        private String ttsUrl;
        @Value("${baidu.tts.secretKey}")
        private String ttsSecretKey;
        @Value("${baidu.tts.tokenUrl}")
        private String ttsTokenUrl;
        // 缓存TTS令牌
        private String ttsToken;
        private long tokenExpireTime; // 令牌过期时间
        private final RestTemplate restTemplate = new RestTemplate();

        /**
         * 获取LLM文本回复和对应角色的TTS语音
        * @param userInput 用户输入
        * @param roleName 角色名
        * @return Map
         */
        public Map<String, Object> getLLMAndVoiceReply(String userInput, String roleName) {
            Map<String, Object> result = new HashMap<>();
            try {
                Role data = (Role) roleService.getRoleByName(roleName).getData();
                String rolePrompt = data.getRolePrompt();
                String roleRequirements = data.getRoleRequirements();
                String roleSkills = data.getRoleSkills();
                // 获取LLM生成的角色文本
                String llmText = getLLMReply(userInput, rolePrompt, roleRequirements, roleSkills);
                result.put("text", llmText);

                // 生成角色语音
                String voiceBase64 = generateRoleVoice(llmText, roleName);
                result.put("voiceBase64", voiceBase64);

            } catch (Exception e) {
                e.printStackTrace();
                result.put("text", "抱歉，AI回复生成失败，请重试~");
                result.put("voiceBase64", null);
          }
            return result;
        }

        /**
        * 获取LLM文本回复
        * @param userInput 用户输入
        * @param rolePrompt 角色设定
        * @return String
        */
        private String getLLMReply(String userInput, String rolePrompt, String roleRequirements, String roleSkills) {
            try {
                String systemPrompt = String.format("【角色设定】%s\n【要求】%s\n【场景触发】%s", rolePrompt,roleRequirements,roleSkills);

                //构造请求体
                JSONObject requestBody = new JSONObject();
                requestBody.put("model", model);

                JSONArray messages = new JSONArray();
                JSONObject systemMsg = new JSONObject();
                systemMsg.put("role", "system");
                systemMsg.put("content", systemPrompt);
                messages.add(systemMsg);


                JSONObject userMsg = new JSONObject();
                userMsg.put("role", "user");
                userMsg.put("content", userInput);
                messages.add(userMsg);
                requestBody.put("messages", messages);

                // 构造请求头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                headers.set("Authorization", "Bearer " + llmApiKey);

                // 发送POST请求
                HttpEntity<String> request = new HttpEntity<>(requestBody.toString(), headers);
                ResponseEntity<String> response = restTemplate.postForEntity(llmUrl, request, String.class);

                // 解析LLM回复
                if (response.getStatusCode().is2xxSuccessful()) {
                    JSONObject llmRes = JSONObject.parseObject(response.getBody());
                    return llmRes.getJSONArray("choices")
                            .getJSONObject(0)
                            .getJSONObject("message")
                            .getString("content");
                } else {
                return "API调用失败，状态码：" + response.getStatusCodeValue();
                }
            } catch (Exception e) {
            e.printStackTrace();
            return "抱歉，AI回复生成失败，请重试~";
            }
        }
         /**
        * 调用百度TTS接口，将角色文本转为对应风格的语音
        * @param text LLM生成的角色文本（如哈利·波特的回复）
        * @param roleName 角色名（如“哈利·波特”“李白”，用于匹配发音人）
        * @return 语音文件的Base64编码（便于前端直接播放，无需保存文件）
        */
        private String generateRoleVoice(String text, String roleName) {
            try {
                String ttsTok = getTtsToken();
                if (ttsTok == null) {
                    return null;
                }
                Role role = (Role) roleService.getRoleByName(roleName).getData();
                int speaker =role.getVoiceType();
                String encodedText = URLEncoder.encode(text, "UTF-8");

                // 构造百度TTS请求参数
                MultiValueMap<String, String> ttsParams = new LinkedMultiValueMap<>();
                ttsParams.add("tex", encodedText);   // 要转换的文本
                ttsParams.add("lan", "zh");          // 语言：中文
                ttsParams.add("ctp", "1");
                ttsParams.add("cuid", "ai_role_play");// 设备唯一标识
                ttsParams.add("tok", ttsTok);       // TTS认证密钥
                ttsParams.add("per", String.valueOf(speaker)); // 发音人（按角色匹配）
                ttsParams.add("spd", "5");           // 语速
                ttsParams.add("pit", "5");           // 音调
                ttsParams.add("vol", "7");           // 音量
                ttsParams.add("aue", "6");           // 音频格式

                // 构造TTS请求头
                HttpHeaders ttsHeaders = new HttpHeaders();
                ttsHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

                // 发送POST请求调用TTS接口，获取音频字节流
                HttpEntity<MultiValueMap<String, String>> ttsRequest = new HttpEntity<>(ttsParams, ttsHeaders);
                byte[] audioBytes = restTemplate.postForObject(ttsUrl, ttsRequest, byte[].class);

                // 将音频字节流转为Base64编码
                return Base64.getEncoder().encodeToString(audioBytes);

            } catch (Exception e) {
                e.printStackTrace();
                return null; // 语音生成失败时返回null
            }
        }

        /**
         * 获取百度TTS的有效令牌
         */
        private String getTtsToken() {
            //  检查令牌缓存
            if (ttsToken != null && System.currentTimeMillis() < tokenExpireTime - 3600000) {
                return ttsToken;
            }
            try {
                // 构造POST请求参数
                MultiValueMap<String, String> tokenParams = new LinkedMultiValueMap<>();
                tokenParams.add("grant_type", "client_credentials");
                tokenParams.add("client_id", ttsApiKey);
                tokenParams.add("client_secret", ttsSecretKey);

                // 构造请求头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

                // 发送POST请求
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(tokenParams, headers);
                ResponseEntity<String> response = restTemplate.postForEntity(ttsTokenUrl, request, String.class);

                // 解析响应，获取令牌和过期时间
                if (response.getStatusCode().is2xxSuccessful()) {
                    String responseBody = response.getBody();
                    JSONObject tokenRes = JSONObject.parseObject(responseBody);

                    // 检查是否返回错误
                    if (tokenRes.containsKey("error")) {
                        return null;
                    }

                    ttsToken = tokenRes.getString("access_token");
                    long expireIn = tokenRes.getLong("expires_in");
                    tokenExpireTime = System.currentTimeMillis() + expireIn * 1000;
                    return ttsToken;
                } else {
                    return null;
                }
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
}
